package C033;

import javax.swing.*;

/**
 * ClassName: Main
 * Package: C033
 * Description:
 *
 * @Author BCXJ
 * @Create 2025/1/2 15:30
 * @Version 1.0
 * @Since 1.0
 */
public class Main {

    public static void main(String[] args) {

        int n = 10000;
        int num1, num2;
        int length = 100;
        // 加法测试
        for (int i = 0; i < n; i++) {
            num1 = (int)(Math.random() * (length + 1) * 2) - length;
            num2 = (int)(Math.random() * (length + 1) * 2) - length;
            if(Math.addExact(num1, num2) != add(num1, num2)) {
                System.out.println(num1 + " " + num2);
                System.out.println("加法测试错误");
                return;
            }
            if(Math.subtractExact(num1, num2) != sub(num1, num2)) {
                System.out.println(num1 + " " + num2);
                System.out.println("减法测试错误");
                return;
            }

            if(Math.multiplyExact(num1, num2) != mul(num1, num2)) {
                System.out.println(num1 + " " + num2);
                System.out.println("乘法测试错误");
                return;
            }

            if(num2 != 0  && (int)(num1 / num2) != div(num1, num2)) {
                System.out.println(num1 + " " + num2);
                System.out.println("除法测试错误");
                return;
            }
        }


        System.out.println("success ~~~");

        System.out.println(div(Integer.MIN_VALUE, 1));
        System.out.println(divPlus(Integer.MIN_VALUE, -1));
    }

    // 限定为int的范围内
    public static int add(int num1, int num2) {
        int mid1, mid2;
        do{
            mid1 = num1 ^ num2;
            mid2 = (num1 & num2) << 1;
            num1 = mid1;
            num2 = mid2;
        }while(mid2 != 0);
        return mid1;
    }


    // 减法
    public static int sub(int num1, int num2) {
        return add(num1, ~num2 + 1);
    }


    // 乘法, 正负都可以
    public static int mul(int num1, int num2) {
        int mid1, res = 0;

        while(num2 != 0) {
            mid1 = num2 & 1;
            if (mid1 != 0) {
                res = add(res, num1);
            }
            num1 = num1 << 1;
            num2 = num2 >>> 1;
        }
        return res;
    }


    // 除法
    // 16 / 3 = 5
    // 16 = 3 * 2 ^ 2 + 3 * 2 ^ 0 + 1;
    public static int div(int num1, int num2) {
        int res = 0;
        int mid1 = num1 < 0 ? ~num1 + 1 : num1;
        int mid2 = num2 < 0 ? ~num2 + 1 : num2;
        for (int i = 30; i >= 0 ; i = sub(i, 1)) {
            if((mid1 >> i) >= mid2) {
                res |= (1 << i);
                mid1 = sub(mid1, (mid2 << i));
            }
        }

        return num1 < 0 ^ num2 < 0 ? ~res + 1 : res;
    }


    // 除法
    // 16 / 3 = 5
    // 16 = 3 * 2 ^ 2 + 3 * 2 ^ 0 + 1;
    public static int divPlus(int num1, int num2) {
        if(num1 != Integer.MIN_VALUE && num2 != Integer.MIN_VALUE) {
            return div(num1, num2);
        }
        if(num1 == Integer.MIN_VALUE && num2 == Integer.MIN_VALUE) {
            return 1;
        }
        if(num1 != Integer.MIN_VALUE) {
            return 0;
        }
        int res = 0;
        if(num2 == -1) {
            return Integer.MAX_VALUE;
        }
        if(num2 != Integer.MIN_VALUE) {
            num1 = add(num1, num2 > 0? num2 : ~num2 + 1);
            res = div(num1, num2);
            res = add(res, num2 > 0 ? -1 : 1);
        }
        return res;
    }
}
